module("Missile", package.seeall)

Missile = class("Missile",
    function()
        return cc.Node:create()
    end)

Missile.__index = Missile

function create(param, skill)
	local self = Missile.new()

	self.param = param
	self.skill = skill

    ccs.ArmatureDataManager:getInstance():addArmatureFileInfo(self.param.armaResPath)
    self._armature = ccs.Armature:create(self.param.armaName)
   -- self._armatureShadow = ccs.Armature:create(self.param.armaName)
   	self._armature:setScale(self.param.armaScale)

	self:addChild(self._armature)
	self.elapsedTime = 0
	self.maxDisX = param.maxDistance
	self.isTurned = false

	return self
end

function Missile:update(dt)
	self.elapsedTime = self.elapsedTime + dt
	
	if (self.target) then
		local x,y = self:getPosition()
		self:setPosition(x + self.speed.x * dt, y + self.speed.y * dt)
		self:detectCollision()
	else
		if (self.elapsedTime >= self.param.duration) then
			self:unscheduleUpdate()
			self:retain()
			self:removeFromParent(false)

			print("大招结束", self.param.route)
		end
	end

	if (self.param.attackDuration and self.param.attackDuration > 0) then
		if (self.elapsedTime > self.param.attackDelay and self.leftDamage > 0) then
			self:damageEffect()
		end
	end
end

function Missile:damageEffect()
	local damage = 0
	if (not self.param.attackDuration or self.param.attackDuration == 0) then
		damage = self.leftDamage
	else
		if (self.timeStamp ~= nil) then
			damage = self.leftDamage * (self.elapsedTime - self.timeStamp) / self.param.attackDuration
		end
	end

	self.timeStamp = self.elapsedTime
	if (damage == 0) then
		return
	end

	self.leftDamage = self.leftDamage - damage

	if (self.target) then
		self.target:attacked(self.skill, damage)
	end

	if (self.param.attackRange and self.param.attackRange > 0) then
		for k,hero in self.hero.enemyCorps do
			if (hero ~= self.target) then
				local d = cc.pGetDistance(cc.p(hero:getPosition()), cc.p(self:getPosition()))
				if (d < self.param.attackRange) then
					hero:attacked(self.skill, damage * (self.param.attackRange - d) / self.param.attackRange)
				end
			end
		end
	end

end

function Missile:detectCollision()
	if (self.collisionTriggered) then
		return
	end

	--计算运动速度和目标的方向是否一致
	local dx = self.target:getPositionX() - self:getPositionX()
	local dy = self.target:getPositionY() - self:getPositionY()

	local dp = dx * self.speed.x + dy * self.speed.y

	if (dp <= 0) then
		self.collisionTriggered = true
	end

	if (self.collisionTriggered) then
		self:onCollision()
	end
end

function Missile:onCollision()
	self:unscheduleUpdate()
	self:damageEffect()
	self:retain()
	self:removeFromParent(false)
end

function Missile:isFinish()
	if (self.param.route == "fix" or self.param.route == "boomerang") then
		return self.elapsedTime >= self.param.duration
	elseif (self.param.route == "line") then
		if (self.speed.x < 0) then
			return self:getPositionX() <= self.endPoint.x
		else
			return self:getPositionX() >= self.endPoint.x
		end
	end

	return false
end

function Missile:checkAttack()
    if (self.param.route == "boomerang") then
        for k, hero in ipairs(self.skill.targets) do
            local curDis = self:getPositionX() - hero:getPositionX()
            local lastDis = self:getPositionX() - self.speed.x - hero:getPositionX()
            if (curDis * lastDis < 0) then
                hero:attacked(self.skill)
            end
        end
    end
end 

function Missile:action(hero)
	self.leftDamage = self.skill:getEffectValue()

	if (self.param.route == "fix" or self.param.route == "boomerang") then
		self._armature:getAnimation():play("default")
	else
		self._armature:getAnimation():play("fly")
		self.target = hero
	end

	local endPoint = hero:getAttackPoint()

	if (self.param.route == "fix") then
		self:setPosition(endPoint)
	else
		self.speed = {x=0, y=0}
		local d = cc.pGetDistance(endPoint, cc.p(self:getPosition()))
		local dx = (endPoint.x - self:getPositionX()) / d
		local dy = (endPoint.y - self:getPositionY()) / d

    	self.speed.x = self.param.speed * dx
    	self.speed.y = self.param.speed * dy
    end

	cc.Director:getInstance():getRunningScene():addChild(self, 8)

	function update(dt)
		self:update(dt)
	end
    self:scheduleUpdateWithPriorityLua(update,1)
end